## 8.4. Managing Print Services

Linux has a fairly complicated printing system, compared to the printing services most personal computers use. It allows many users to print documents at the same time, and each user can send documents from one or more applications without waiting for the previous document to finish printing. The printing system processes the files to be printed correctly on different kinds of printers connected to the computer in different ways. If you print on a network, files can be created on one host and printed out on a printer controlled by another host.

The whole process happens without much fuss, when you press the Print button in an application or issue a command, such as `lpr`, to print a document. That document does not go directly to the printer, though, because it might already be busy. Instead, the document is stored in a temporary file in a directory called the printer spool directory. As the word "spool" suggests, the documents get taken out of the directory one by one as the printer becomes free. Each printer has its own spool directory.

When Linux starts, it sets up a printer daemon (an independently running process) called `lpd`. This process waits around checking each spool directory for files that should be printed. When the process finds a file, it makes a copy of itself. The new `lpd` takes control of the print spool where the file was placed and queues it for printing. It won't send the next file to that printer until the last file has finished printing. The master `lpd` starts an `lpd` for each spooling directory on the system when a file is sent to it, so there may be as many `lpd` daemons running as the number of active spooling directories plus the master `lpd`. Each subordinate `lpd` stays around until its spool directory is empty.

Your Linux installation process associates the printer port on your system to a device named in the /dev directory. You must then link that device name to the convenient printer names you use in your commands; that's the role of the printer capability file called /etc/printcap.

Another key task in printer management is to make sure you have filters in place for `lpd` to use when formatting documents for printing. These filters are also specified in the /etc/printcap file, and we'll talk a lot about them in this section.

There are several printer-support packages for Linux. Most distributions use the BSD-derived package that contains the `lpd` printer daemon. These packages include a set of utilities and manpage documents to support traditional Unix-style printing on Linux. The BSD printing system doesn't have as many administrative tools or user controls as, for example, the System V Unix printer-management system (which uses the `lpsched` daemon), but each user controls the files that she sends to the printer. This section describes installation and configuration of the BSD printer-support package. (The various printing utilities are described in the section "Section 9.5, "Printing"" in Chapter 9, "Editors, Text Tools, Graphics, and Printing".)

Some Linux distributions provide a printer-management tool that simplifies printer installation and management through a graphical user interface. These tools are documented by the vendor that supplies them. They manage printing by controlling the same tools and files we are about to describe, but with less fine control. They can save you a lot of trouble in getting started, but they don't always get things right. If you want to correct an installation set up through these tools or want to improve on their performance, you still should work through the procedures in this section.

### 8.4.1. Checking Printer Hardware

Before you set up printer services, be sure the printing devices are online. If you also use another operating system, such as OS/2, Coherent, or MS-DOS, you can exercise the hardware to ensure that it is connected properly and working before loading Linux. Successfully printing a document from another operating system immediately eliminates one major source of woe and headscratching. Similarly, if you are going to use printer services on a network, your system should be on the network and all protocols functioning before proceeding.

You install printer services as the root user, with superuser privileges. The super-user is the only user besides the `lpd` print daemon able to write directly to a printer by directing output to the corresponding output device. Other users cannot send output directly to the printer and must instead use the printer utilities to handle printing tasks.

Before you get started, you can abuse your root privileges to verify that your system's assigned device files actually have a valid link to the physical device. Just send a brief ASCII test file directly to the printer by redirection. For instance, if you have a printer on your first parallel port, its device name is probably either /dev/lp0 or /dev/lp1, depending on your installation. The following command outputs some text suited for testing a printer setup, which you can redirect to your printer. (If you have an early PostScript printer, you may need instead to send it a small PostScrip test file to prevent it from getting confused.)

>     lptest > /dev/lp1

The `lptest` utility is designed to conveniently exercise an ASCII printer or terminal to make sure it is working correctly. It sends a prepared file composed of the 96 ASCII characters in a sequence that creates a "ripple" or "barber-pole" output effect. The default output of `lptest` on Linux is 16,000 characters arrayed in 79-character lines, long enough to require more than one page to print. If you run `lptest` with no arguments, it prints the standard output to your screen, and you can see what should be sent to the printer. The `lptest` command allows you to trim the width of the output column and to limit the number of output lines. For example, to display an output 35 characters wide, limited to six lines, you would enter:

>     lptest 35 6

The output should look much like this:

>     !"#$%&'()*+,-./0123456789:;<=>?@ABC
>     "#$%&'()*+,-./0123456789:;<=>?@ABCD
>     #$%&'()*+,-./0123456789:;<=>?@ABCDE
>     $%&'()*+,-./0123456789:;<=>?@ABCDEF
>     %&'()*+,-./0123456789:;<=>?@ABCDEFG
>     &'()*+,-./0123456789:;<=>?@ABCDEFGH

This output is short enough that you can see the result of redirecting it to your printer without wasting a lot of paper and long enough to identify many obvious problems with printing.

Of course, you can also use the `cat` command to direct a file to the printer. To send a PostScript test file to a PostScript printer, for example, type:

>     cat testfile.ps > /dev/lp1

If you have a serial printer, try directing output to the serial port to which it is connected. For the first serial port (COM1: in MS-DOS) try something like:

>     lptest > /dev/ttys0

or:

>     lptest > /dev/ttyS0

Make sure you send to the correct serial port; don't try to output the file to a serial mouse, for example. If your serial printer is on the second serial port, for example, it is addressed as /dev/ttyS1 or /dev/ttys1.

If you have a page printer that buffers a partial page, after it stops printing you may need to take the printer offline and press the Form Feed button to get it to print the last partial page. Don't forget to put the printer back online afterward. (If your printer does buffer partial pages, you want Linux to send the formfeed character to the printer, either by forcing it through the /etc/printcap entry for the printer or by having the printer filter append it to the end of the file. We'll discuss these options later.)

If your little test resulted in "laddered" text (text that looks something like the following example) and then continued off the page, the printer did not insert a carriage return at the end of each line:

>     !"#$%&'()*+,-./0123456789:;<=>?@ABC
>                                        "#$%&'()*+,-./0123456789:;<=>?@ABCD
>                                                                           #$

You might be able to figure out what went wrong here. Text files in Unix use just a newline (also known as a linefeed, ASCII code 10) to terminate each line. MS-DOS uses both a newline and a carriage return. Your printer was therefore set up to use MS-DOS-style line endings with both newline and carriage-return characters at the end of each line. In order to print a text file from Unix, you can install a printer filter to accommodate the Unix newline, or you can reconfigure your printer to properly return to the start of the line on receipt of a newline character. Often this is simply a matter of setting a dip switch. Check your printer manual. (Be careful about changing your printer characteristics if you use multiple operating systems.)

Laddering won't be an issue if you have a printer using a page-description language such as PostScript (the universally used page-layout language from Adobe), and you always filter plain text into that output form before printing. Filtering is described later in this chapter.

### 8.4.2. Gathering Resources

OK, you have your printer hardware set up and connected. You should collect hardcopy of your resource documents (at least the manpages for the print utilities and files described here, and the Printing HOWTO file). Also, it is useful to have the technical specifications for your printer. Often these are no longer provided when you buy your printer, but you can usually download the information you need from an FTP site or BBS operated by the printer manufacturer. While you are retrieving such information, look around and see if there is documentation (such as a description of printer error messages and their meanings) that can help you troubleshoot and manage your printer. Most printer manufacturers also offer a technical manual for the printer that you can buy. This may or may not be the same volume as the service manual.

For example, on the Hewlett Packard FTP site, ftp://boi.external.hp.com, you can retrieve printer technical data sheets; product specs; port-configuration information; PostScript, PCL, and HP-GL files for testing your printers (and filters); descriptions of printer control sequences you can pass to the printer to control its behavior; and documents telling how you can integrate `lpd`-based printing services with HP's JetAdmin package (and thereby with Netware-networked printers as well).

Now, before starting, take a deep breath; be patient with yourself. Printer services configuration is a skill that takes time to develop. If you have sufficiently standard equipment and successfully use one of the new-fangled printer management utilities to quickly and efficiently install and configure printer services, celebrate! Then note that you can probably fine-tune the installation for better performance by applying the procedures we describe next and perhaps by using filters and utilities written specifically to support all the features of your printer model. If you decide to revise a successful printer installation, make sure you take notes on the changes you make so you can find your way back if your changes don't do what you expected.

### 8.4.3. Choosing Printer Software

In order to print from Linux, you need to install the BSD print system. This provides basic tools, but it does not support modern printers. Indeed, it was designed to support line printers and devices common to the computer rooms of the '60s and '70s. In order to support modern printers, powerful supplemental packages provide the features most users think of as essential. (The ftp://metalab.unc.edu FTP site and its mirrors archive the packages we mention here.)

In this section, we discuss some important packages to support modern print services. We assume your system will have at least the `groff` formatter, the Ghostscript page-formatting package, and the `GNU Enscript` filter packages, which are described in Chapter 9, "Editors, Text Tools, Graphics, and Printing". Most Linux distributions already include these as well as other formatting and printing utilities. If yours does not, you can retrieve them from the usual Linux FTP sites or take them from the CD-ROM of another distribution.

It matters where you get formatting and filtering packages. If you receive Ghostscript from a European distribution, for example, it probably defaults to an A4 paper format rather than the 8.5x11-inch paper format kept in U.S. binary archives. In either case, the default can easily be overridden through an `lpr` option passed to the filter. Alternatively, you can build the tools from source.

The trend in printer technology is away from character-oriented output and toward adoption of a page-description language (PDL) that provides sophisticated graphics and font control. By far the most popular of the PDLs is PostScript, which has been widely adopted in the Unix and Internet communities. A major reason for its acceptance is Ghostscript, a PostScript implementation copyrighted by Aladdin Enterprises. A version is also distributed under the GNU Public License through the Free Software Foundation, along with a large font library, that can be used with either version or other PostScript interpreters.

Ghostscript implements almost all the instructions of the PostScript language and supports viewer utilities, such as Ghostview, that allow PostScript documents to be displayed in X windows. Similarly, excellent filters are readily available that convert PostScript output into other printing languages, such as Hewlett-Packard's PCL, and into forms printable as raster output on inkjet, dot matrix, and laser printers. Ghostscript is indispensable if you do any kind of printing besides character-based output and is easily extensible. The Ghostscript package supports Adobe type 1 and 3 PostScript fonts and provides a number of utilities for graphic format conversion and filtering. It can even generate PDF files, i.e., files that conform to the Adobe Portable Document Format specification.

Ghostscript may be insufficient to use by itself, however, because it doesn't provide printer control to switch between PostScript and text modes. Although Ghostscript does provide a filter that provides this capability (and more), the `nenscript` filter meets the tests of simplicity, flexibility, and reliability for most systems, so we document it here.

A typical Linux formatting and printing system might primarily use `groff` to format, creating PostScript output that is then processed by Ghostscript for printing and display. Often there will be parallel printing systems installed that perform document formatting to suit preferences of various users or accommodate files received in different typesetting formats.

### 8.4.4. Checking Print Utilities

You probably also want to install the TeX formatting package. Even if you do not install the full TeX distribution, you should at least install the `xdvi` utility, in order to view TeX output and Texinfo files in an X window. Other filters can process DVI output into forms such as PostScript (`dvips`) or PCL (`dvilj`) if you have an aversion to the Ghostscript package or need to use native printer fonts for efficient data transfer and rapid printing.

The Lout package is also worthy of consideration as an efficient and compact package to format documents for PostScript output. It supports Level 2 PostScript and the Adobe Structuring Conventions, takes comparatively little memory, and comes with good enough documentation to learn quickly. Lout doesn't create an intermediate output form; it goes directly from markup input to PostScript output.

To support graphics work and X Window System utilities, you probably want to install other tools, some of which probably come with your distribution. A collection of current versions of the most popular print support packages for Linux can be found at the ftp://metalab.unc.edu Linux archive, in /pub/Linux/system/printing. The `netpbm` and `pbmplus` packages support a large variety of graphic file format conversions. (Such formats have to be converted to PostScript before you try to print them.) The Ghostview package provides display tools to view PostScript files in an X Window System environment, and also provides PostScript and PDF support for other packages, such as your Web browser.

The ImageMagick package, described in Chapter 9, "Editors, Text Tools, Graphics, and Printing", deserves special mention. It lets you display a large number of graphic formats in an X window. (It uses Ghostview and Ghostscript when it needs to display a PostScript image.) Most of the graphics files you can print you can also display using ImageMagick.

A "magic" filter package may also save you much grief in configuring and supporting different document output formats. We will discuss the APSfilter magic filter package (not in great depth) but you may prefer the Magic-Filter package instead. Both are available at the ftp://metalab.unc.edu FTP archive. For more on magic filters, see the section "Section 8.4.9, "Magic Filters: APSfilter and Alternatives"" later in this chapter.

If you want to support fax devices, the `tiffg3` utility can be used with Ghostscript to output Group III fax format files. To control a Class 1 or Class 2 faxmodem on your Linux host, you can use the efax package, which is provided in many distributions, or you can install and configure the more capable, but more complex, FlexFax package.

There are additional tools to support double-sided printing on laser printers and packages that convert PostScript to less common printer-control languages to support Canon and IBM Proprinter devices, for example. There is a package to support printing in Chinese on laser printers and bitmap devices. Most of these packages don't directly affect management of print services so we don't describe them in detail here, but this is a good time to install them if you wish to use them.

For the benefit of your users, make sure that all the manual pages for the packages you install are prepared properly when you complete your installations. Then run `/sbin/mkwhatis` (`/usr/bin/mandb` on Debian) to build the manual page index file that facilitates locating information online. Some packages, such as Ghostscript, also provide additional documention that you can print or make available on the system for reference. (Linux distributions tend to omit these documents, but you can FTP them from the sites where the software packages are developed and maintained. The GNU archives of the Free Software Foundation, for example, are accessed by anonymous FTP at ftp://GNU.ai.mit.edu.)

Filter selection and use is described "Section 8.4.7, "Print Filters"" section later in this chapter.

### 8.4.5. Setting Up the Printcap File

The essence of printer configuration is creating correct entries in the printer capabilities file, /etc/printcap. A simple printcap entry for an HP Laserjet 4MP laser printer attached to the first (bidirectional) parallel port on an ISA bus PC might look something like this:[34]

>     ljet|lp|ps|Postscript|600dpi 20MB memory|local|LPT1:\
>          :lp=/dev/lp0:rw:\
>          :sd=/var/spool/lpd/ljet4:mx#0:mc#0:pl#72:pw#85:\
>          :lf=/var/log/lpd-errs:if=/usr/local/cap/ljet4:

Don't be scared. After reading the following sections, you will find yourself browsing printcap files with ease.

> [34]In this chapter, we use ljet4 in several examples. Be aware that the HP Laserjet 4 model is available in several versions. Some Laserjet 4 models are PCL5 printers only, and others use PostScript. Unless you are aware that such things can happen, you can find it very frustrating trying to debug a printer filter that is expecting, for example, PostScript, when Ghostscript is passing it PCL5 input.

The /etc/printcap file should accommodate every printer and printer port or address--serial, parallel, SCSI, USB, or networked--your system will use. Make sure it reflects any change in hardware. And as always, be aware that some hardware changes should be performed only when power to your system is shut off.

### 8.4.5.1. Printcap file format rules

The printcap file format rules, briefly, are:

- A comment line begins with a pound sign (#).

- Each "line" of the printcap file defines a printer. A line that ends with a backslash character (\) is continued on the next line. Be very careful that no space or tab character follows the backslash character on the line. Traditionally, a continuation line is indented for readability. Multiple printer definitions can use the same actual printer, applying the same or different filters.

- Fields in the line are separated by colon characters (:); fields can be empty. However, a printcap line entry cannot be an empty field.

- Traditionally, the first field in the entry has no preceding colon.

- The first field of the entry line contains names for the printer, each separated by a vertical bar character (|). In the earlier example entry, this portion is the name field:

  >     ljet|lp|ps|Postscript|600dpi 20MB memory|local|LPT1

  Printer naming is discussed in detail in the next section. You should create a subdirectory of /var/spool/lpd with the same name as the first printer ID listed in each printcap entry. However, the actual print spool that is used is assigned by the `sd` variable for the printcap entry; if the `sd` variable doesn't point to the actual print spool directory, any file sent to that printer definition will vanish.

- There must be at least a default printer entry in printcap. If a printer is named lp, that printer is used as the default system printer. Do not confuse the lp default printer name with the `lp` local printer variable, which is described next. We recommend you use lp as an alias (one of the names after the | characters) rather than the primary printer name (the first in the list), so you can switch the default printer without difficulty.

- Each local printer must have an `lp` variable set. In the previous example, the variable was set by this segment of the printcap entry:

  >     lp=/dev/lp0

- For compulsive and sometimes practical reasons, some administrators recommend that the entries of the printcap file be kept in alphabetical order.

### 8.4.5.2. Printer names

Most printer entries traditionally begin with a short printer name entry in the first field, at least one fuller printer name, and one longer explanatory entry. Thus, both ljet and PostScript are names for the printer whose nameline is:

>     ljet|lp|ps|Postscript|600dpi 20MB memory|local|LPT1:

Documents can be output to any printer named in a nameline in /etc/printcap.

You might name your printers after the model (hp, epson) or the type of printer (ps, pcl) or its specific modes. The DeskJet 540, for example, is a printer that should have two definitions in the printcap file, one for black print and another for color. The filters you use to support it are likely to be those for DeskJet 500 or 550C. For simple administration, you can assign printer names that are the names of a filter or filter parameter used for a specific device. Thus, if you have one LaserJet 4 and will use the ljet4 filter only for it, ljet4 is one logical name for the printer. Similarly, a dot-matrix printer might be named 72dpi when accessed via its low-resolution printer definition line, and have the name 144dpi when accessed in a higher resolution.

If you use a printer administration utility that comes with your Linux distribution, you may have to follow certain arbitrary rules in preparing your printcap entries in order to get the tools working. For example, if you use Red Hat's printer manager utility provided on the administrator's desktop, you may need to make sure that hp is the first name of the first active printer entry in the printcap file. This means that when you need to switch default printers, you need to move the new default printer to the top entry of the list and then remove the hp name from the old default printer and prepend it as the first name of the new default printer. In order to prevent confusion in use of the spool queues, you should just leave the /var/spool/lpd/lp directory set up and create a new directory with the actual name of the spool directory that corresponds to the name by which you actually will address the printer. Thus, if you want to send your files to print on a printer named moa, you will need to create a directory named /var/spool/lpd/moa, with appropriate permissions, and specify that directory as the printer spool for that printer. Setting up printer directories is described in the next section.

### 8.4.5.3. The rest of the printcap variables

The printcap file provides a number of variables that you can define. Some are fairly universal, and others are specific to the implemented features of `lpd`. Most variables are provided to specify page parameters, files and directories, filters, communication channel settings, and remote access control. Any time you prepare a printcap file on a new system, read the printcap manual page to make sure you use the correct variable names. Variables set in a printcap entry that are not recognized are passed through to the filter for processing.

The printcap variables described here are listed in roughly their order of importance. Some variables are boolean, and are considered set if they are present. Others are set with the assignment operator (=) or numeric value operator (#) and a value; the variable preceedes the operator and the string or number follows the operator. Examples of the variables described in the following list are included in the contrived sample /etc/printcap file that follows. The printcap manual page has a more complete listing of variables recognized by `lpd`:

`sd`

  Specifies the spool directory used by the printer. Spool directories should all be in the same directory tree (on a fast hard disk), which is usually /var/spool. Spool files are defined even for remote printers. Each spool file should have one of the names assigned to the printer it serves.

`lp`

  Assigns a local printer device, typically connected through parallel port, serial port, or SCSI interface. The `lp` variable must be assigned to a device file in the /dev directory, which may be a link to a physical device. The `lp` variable must be assigned if there is a local printer. This variable should not be assigned if the `rp` variable is assigned (that is, the print spool manager is on another host).[35] If `lp` assigns a serial device, the baud rate must be specified with the `br` variable.

  > [35]A special case arises where the printer to be addressed is a true networked printer (that is, it has its own IP address). In that instance, the `lp` variable assigns the name of a dummy file that is used for setting a temporary lock on the file when the networked printer is in use. The documentation for the networked printer should describe the procedure for setting up and managing print services to access it.

`lf`

  Specifies the log file for storing error messages. All printers should have this variable set and normally use the same error log file. Error entries include the name of the printer and can reveal problems with the user's printer environment, the host configuration, the communications channel that is used, and sometimes the printer hardware itself.

`rw`

  This variable should be specified if the printer is able to send data back to the host through the specified device file. The `rw` variable tells `lpd` that the device should be opened for both reading and writing. This can be useful for serial or SCSI PostScript printers, for example, because they may return fairly useful error messages to `lpd`, which stores them in the error log.

`mx`

  Specifies the maximum size of a print job in the spool. A value of zero sets no limit (the default, `mx#0`), and any other value sets the maximum file size in blocks. Most of the time you don't want to set a limit, but you could, for example, set a value slightly smaller than the expected minimum space available on a disk.

`if`

  Specifies an input filter to use. If you do not specify an input (`if`) or output (`of`) filter, the system uses the default /usr/sbin/lpf filter. For some MS DOS-style character printers, this is sufficient. Other useful filters are provided in the formatting utilities, and there are some flexible "magic filter" packages that will determine (usually correctly) the filtering to apply from the content of the data file passed to it. See the section "Section 8.4.7, "Print Filters"" that follows.

`of`

  Specifies an "output" filter to use. When you assign the `of` variable and don't assign the `if` variable, the system uses the filter once when the device is opened. All queued jobs are then sent without reapplying the filter until the queue is exhausted (and `lpd` removes the lock file from the spool directory). This is not normally useful, but it could serve such purposes as sending faxes to a faxmodem for dialed connection over a telephone line.

  When you assign both the `if` and `of` variables, the `if`-specified filter normally processes the file, but the `of`-specified filter prints a banner page before the input filter is applied. Using both input and output filters effectively on the same print queue is notoriously difficult.

`br`

  Specifies the data-transfer rate (baud rate) for a serial port. You must supply this value if the printer is accessed via serial port. A pound sign precedes a numeric value that expresses the data-transfer rate in bits per second (not truly the baud rate, which is an effective rate of flow as opposed to the maximum rate of flow). The specified rate should not exceed any hardware limits. For example, if your serial port is capable of a 57.6 Kbps rate and the printer can process 28.8 Kbps, the assigned rate should not exceed that lower limit (perhaps `br#19200`). Supported bps values are the usual multiples for serial communications: 300, 600, 1200, 2400, 4800, 9600, and so on. A number of additional data conditioning values may be set if you do assign a `br` value, but most of them aren't useful for typical Linux installations. The default behavior is probably acceptable for your printing purposes, but if you intend to print via serial port, study the `br`, `fc`, `fs`, `xc`, and `xs` variables in the printcap manual page.

`pl`

  Specifies the page length as the number of lines using the default font characters for character devices (and printers that can use a character mode). An example is `pl#66` for an 11-inch page at six lines per inch. This value allows space for cropping and accommodates limits of some other devices, such as inkjet printers that cannot print to the bottom of the sheet or the edge of the paper. Normally used in conjunction with the `pw` variable.

`pw`

  Specifies the width of the page supported, in characters, using the default font characters for character devices. `pw` is set like the `pl` variable; for example, `pw#85` for 10 characters per inch with an 8.5-inch printable page width.

`px`

  Specifies the number of pixels to use on the X axis for a bitmap image file sent to a raster device.

`py`

  Specifies the number of pixels to use on the Y axis for a bitmap image file sent to a raster device.

`sh`

  Suppresses printing of a header or banner page. In most cases, you should set this.

`rp`

  Specifies the name of a remote printer to use. This variable cannot be set if the `lp` variable is set for the same printer. The printer handling is performed by the remote host assigned in the `rm` variable, which is required when `rp` is set. Usually, the only variables set along with these are spooling and error recording. See the example that follows.

`rm`

  Specifies a remote host that controls the remote printer you print to. The specified host ID assigned by `rm` should be one that is known to the network services as installed (set up in /etc/hosts or known through NIS, for example).

`rs`

  Restricts access to local printers to those users with an account on the system.

`rg`

  Specifies a restricted group that can use the printer. For example, to reserve a defined printer for superuser, enter `rg=root`.

`sf`

  Suppresses the formfeed sent to the printer by default at the end of a print file.

`ff`

  Assigns the formfeed character or string the device should use. The default is Ctrl-L (equivalent to `ff='\f'`), which is usual for most devices.

`fo`

  Sends a formfeed character to the device before sending the file.

`mc`

  Specifies the maximum number of copies you can print. Values are the same as for the `mx` variable; usually you want to allow unlimited copies (`mc#0`), which is the default.

`sc`

  Suppresses multiple copies (equivalent to `mc#1`).

Example 8-1 contains a sample printcap file that shows off many of the variables discussed in the previous list.

#### Example 8-1. Sample /etc/printcap file

>     # Fare well, sweet prints.
>     hp|bat|west|spigot|berkeley|TI MicroLaser Turbo:\
>          :mx#0:rp=lp:\
>          :lp=:sd=/var/spool/lpd:rm=spigot.berk.ora.com:\
>          :lf=/var/log/lpd-errs:
>     # To the print room
>     kiwi|810|rint|Big Apple|Apple 810 via EtherTalk:\
>          :lp=/var/spool/lpd/kiwi:sh:\
>          :sd=/var/spool/lpd/kiwi:pl#72:pw#85:mx#0:\
>          :lf=/var/log/lpd-errs:if=/usr/local/cap/kiwi:

>     # big bird--agapornis via shielded serial access
>     samoa|S|PostScript|secure|QMS 1725 by serial adapter:\
>          :lp=dev/tty01:br#38400:rw:xc#0:xs#0400040:sh:\
>          :sd=/var/spool/lpd/samoa:pl#72:pw#85:mx#0:mc#0:\
>          :lf=/var/log/lpd-errs:if=/usr/local/cap/samoa:
>     # agapornis via printer room subnet (standard access)
>     moa|ps|QMS 1725 via Ethernet:\
>          :lp=/var/spool/lpd/moa/moa:rm=agapornis:rp=samoa:\
>          :sd=/var/spool/lpd/moa:mx#0:sh:\
>          :lf=/var/log/lpd-errs:if=/usr/local/cap/samoa:

### 8.4.6. Configuring Ghostscript

Ghostscript is included in standard Linux packages; it is an essential utility in an X Window System environment and is useful even if you don't run X. Ghostscript can provide graphics output to a standard VGA display even where no window manager is running and can also process and create PostScript-formatted files without a graphics display. You can examine what devices Ghostscript is configured to recognize and format for on your system by entering Ghostscript in interactive mode. If you enter:

>     $ gs

Ghostscript should load in interactive mode and await your instructions:

>     GS>

You can then query the devices that Ghostscript is configured to recognize, and Ghostscript will display them:

>     GS> devicenames ==
>     [/pkm /sj48 /la75plus /t4693d2 /pjxl300 /cdj500 /mgr8 /tifflzw /ppm
>     /okiibm /la70 /iwlo /ljet3d /pjxl /cdjcolor /mgrgray8 /tiffg32d /pnm
>     /oce9050 /declj250 /bjc600 /ljet2p /st800 /stcolor /png256 /mgrgray2
>     /tiffcrle /pgnm /m8510 /lbp8 /bj200 /pdfwrite /pjetxl /eps9high
>     /pnggray /bitcmyk /faxg32d /pgm /jetp3852 /epson /lp2563 /paintjet
>     /appledmp /x11cmyk /pcx24b /bit /dfaxlow /pbm /cp50 /tek4696 /lj4dith
>     /djet500c /x11 /pcx16 /tiff24nc /pkmraw /ccr /ln03 /t4693d4 /deskjet
>     /cdj550 /pcxmono /tiffpack /ppmraw /r4081 /la75 /nullpage /ljet4 /iwlq
>     /cdjmono /mgr4 /tiffg4 /pnmraw /oki182 /la50 /iwhi /ljet3 /cdj850
>     /cdeskjet /png16m /mgrgray4 /tiffg3 /pgnmraw /necp6 /lips3 /epsonc
>     /laserjet /x11mono /png16 /mgrmono /faxg4 /pgmraw /imagen /bjc800
>     /bj10e /pj /eps9mid /x11alpha /pngmono /bitrgb /faxg3 /pbmraw /ibmpro
>     /ap3250 /ljetplus /dnj650c /pcx256 /psmono /dfaxhigh /xes /lj250
>     /t4693d8 /djet500 /miff24 /pcxgray /tiff12nc]
>     GS> quit
>     $

If you are not using X, and Ghostscript fails to initialize when you try to invoke it, complaining that it cannot open an X display, then the first device Ghostscript loaded in its build file was the X Window System device; Ghostscript uses the first device as its default device. You can work around this problem by specifying some other device that Ghostscript will have installed, for example, `gs -sDEVICE=epson`. You can guard against the problem in the future by setting a global GS_DEVICE environment variable to some other device on your system that can be opened by Ghostscript.

If you have such an unusual output device that the default Ghostscript installation does not support it, you need to rebuild Ghostscript to support the device, or else process your output files through a filter that converts it to a form usable by your output device. Ghostscript comes with makefiles and is easy to build if you follow the Ghostscript documentation that comes with the distribution.

The more graphics utilities, X window managers, games, and applications you use, the more likely you will need to reinstall Ghostscript to suit your requirements. Read the Ghostscript documentation before running the makefile that comes with the package. (This requires that you have `gcc` installed on your system.)

You can define the GSDIR environment variable to locate the path of the ghostscript command, and to set GS_LIB variables if you need to build Ghostscript utilities and add them to your installation. For example:

>     export GSDIR=/usr/bin
>     export GS_LIB=/usr/lib/ghostscript:/usr/local/lib/fonts:/usr/X11R6/fonts

Set the GS_LIB_DEFAULTS variable before you make a new build of Ghostscript; see the `gs` manual page.

The Ghostscript package also contains some PostScript programs that provide useful print-support functions, including some sophisticated printing capabilities we do not document here. The gs_init.ps file, in particular, affects the general behavior of Ghostscript. Additional scripts (filters, shell scripts, and so on) can be found in /usr/lib/ghostscript or /usr/local/lib/ghostscript. You may find it useful to examine the ps2epsi.ps utility, which converts PostScript into encapsulated PostScript, and the ps2ascii.ps utility, which converts PostScript files into plain text.

### 8.4.7. Print Filters

Every document passes through a filter before going to the printer, thanks to the `if` variable in the printcap file. A print filter can be found in a Linux distribution, acquired from the printer's vendor, found on the Net, or even made yourself from scratch or by cobbling together existing filters and shell utilities.

An input filter can also be used to restrict use of a printer to a specific user or group, or users with accounts on a particular host. Typical `if`-assigned filters are executable shell scripts that process the text file, but they can be any program that can take the input data stream and process it for output to a printer.

It is increasingly common for commercial Linux distributions to build a filter interactively. While you can usually improve on such a filter, it can help to use one as a starting point. The Red Hat distribution, for example, created the following shell-script filter (named /var/spool/lpd/ljet4/filter)[36] on one of our systems from information provided to it in the printer manager window and from default assumptions. The /etc/printcap was modified to specify the use of this filter, which proved to be perfectly functional on our system:

> [36]Putting a filter in a printer's spool directory is a convenient technique for a printer management program to use when setting up your printer system. You may prefer to keep all your print filters and graphics conversion filters in the same directory (following the Unix tradition), such as /usr/sbin or /var/spool/lpd/filters. Of course, in that case, each filter you create must be uniquely named.

>     #!/bin/sh

>     DEVICE=ljet4
>     RESOLUTION=600x600
>     PAPERSIZE=letter
>     SENDEOF=

>     nenscript -TUS -ZB -p- |
>     if [ "$DEVICE" = "PostScript" ]; then
>     	cat -
>     else
>     	gs -q -sDEVICE=$DEVICE \
>     		-r$RESOLUTION \
>     		-sPAPERSIZE=$PAPERSIZE \
>     		-dNOPAUSE \
>     		-dSAFER \
>     		-sOutputFile=- -
>     fi

>     if [ "$SENDEOF" != "" ]; then
>     	printf ""
>     fi

>     exit 0

There's nothing exotic about this filter. First it sets some variables that appear later as arguments in the Ghostscript command. The script passes output through `nenscript` and passes PostScript files to the `gs` Ghostscript utility. (In this particular case, the automatically generated filter will never invoke `gs` because DEVICE never equals "PostScript" in the `if` test.) If your printer doesn't eject the final pages of output, you can force it to by setting the SENDEOF variable near the top of the file. For example:

>     SENDEOF='\f'

will cause a formfeed to be sent to the printer when it reaches the end of a file.

You might modify such a script and substitute a filter specifically designed for a LaserJet 4 printer, such as the actual ljet4 filter package, for example, and accommodate printing of TeX DVI files by filtering them through `dvips` and feeding them to Ghostscript. There is an elementary discussion of how to create a filter in the Linux Printing HOWTO.

If you use a character printer that expects a carriage return at the end of each line, it will be unhappy with Linux, which follows Unix fashion in terminating a line with a linefeed, but no carriage return. To force correct treatment of newlines on these printers, the filter has to insert the carriage return. This can be done by writing the processing into the filter, or, alternatively, by using a filter that already has the capacity of inserting the character.

Some printer vendors provide filters and utilities for their printers, especially where the usual solutions are likely to be inadequate to take advantage of the printer's capabilities. For example, Hewlett-Packard provides a JetAdmin package with filters to use with their TCP/IP network-addressed LaserJet printers.

The default filter that comes with the BSD print-management package is /usr/sbin/lpf. This filter is undocumented and probably best ignored, unless you wish to retrieve the C source and trace through the program to learn its capabilities. (The full BSD source for this can be found in the lpr-secure package in the printing directory from ftp://metalab.unc.edu.)

Most of the print-filtering needs you have were long ago resolved, and there are filters out there to meet your needs. By running:

>     apropos filter

you can probably identify several print filters installed on your host.

Changing filters is simple. You need only change the /etc/printcap input filter specification (`if`) to specify the filter you want, and then kill and restart `lpd`, which you can do using the `lpc` utility. Enter (as root):

>     lpc restart all

The `lpc` utility reports any `lpd` processes it kills, then it restarts `lpd`. If there are files in a print spool waiting to print, `lpd` also reports that an `lpd` daemon for that printer has been started. The `lpc` printer control utility is described later in this chapter, in the section "Section 8.4.12, "Controlling Printer Services with lpc"."

Study the manual page for a filter and then pass some test files through before adopting a strange print filter. We have found that filters don't always perform "as advertised" in their manual page; often the document is obsolete or the filter was compiled by someone using different configuration parameters than the document assumes. There is no substitute for testing all the things you expect the filter to do before adopting it. Two good filtering packages, `nenscript` and APSfilter, are discussed in the next section.

### 8.4.8. The nenscript Filter

The `nenscript` filter is a typical modern filter for Linux. You should find it in /usr/bin/nenscript if it was provided in your Linux distribution. Otherwise, it may be installed in /usr/local/bin. `nenscript` controls headers, footers, rotation of text, and so on, and produces PostScript output conforming to the Adobe Structuring Conventions from plain ASCII input (by calling Ghostscript). It sends output to the printer specified by the user's NENSCRIPT environment variable, if set, or the user's PRINTER environment variable otherwise. If neither variable is set, `nenscript` uses the default printer that `lpr` wants to use.

If `nenscript` is called using the -Z option, it is supposed to pass PostScript files through without altering them. `nenscript` examines the input file, and if the first two characters in the input file are `%!`, `nenscript` suppresses formatting. Since this output "type-checking" is primitive, it is easily fooled. Obviously if the first two characters happen to be something other than `%!`, perhaps because a formfeed is the first character, for example, the file will not be recognized as PostScript even if it is. This can easily happen if some filter processing takes place before the file passes through to `nenscript`. Of course, a file can also have `%!` as the first characters and not be PostScript (or could be nonconforming PostScript) and may not therefore be handled properly if passed to a PostScript printer. There are smarter filters for this type of checking, including Magic-Filter or APSfilter, but `nenscript` may easily meet your needs, especially if you print only to a PostScript printer.

If you use the `nenscript` filter for a PostScript printer on your system, therefore, you could specify the -Z option in the NENSCRIPT environment variable for all user shells by default, in order to pass through the PostScript received by the filter.

There are other comparable filters. The `nenscript` filter emulates the traditional Unix enscript filter. A shell script provided in the `nenscript` package invokes `nenscript` configured to behave as though it were another (similar) traditional Unix filter, `pstext`.

To use `nenscript` to filter your print files, make sure `nenscript` is installed in an appropriate path, and then set the printers for which you want `nenscript` to filter to point to a filter that invokes the `nenscript` filter. You may find that the printcap entry can point directly to the `nenscript` filter if you set a system-wide default NENSCRIPT variable to control its options, or you can create a simple processing filter that calls `nenscript`, much like the sample configuration file shown earlier. Verify file and directory ownerships and permissions after you have altered the printcap file and set up filters.

### 8.4.9. Magic Filters: APSfilter and Alternatives

The most versatile filters are the so-called "magic" filters. A magic filter examines the contents of a file passed to it, and filters the output for printing based on the what it learns from the format of the information. If it sees the file is DVI routed to a PostScript printer, for instance, it will apply another filter (perhaps `dvips`) to convert the data into PostScript for printing. This is very convenient, but on occasion, the filter can make a mistake. If that happens, the user can resubmit the file with command-line options that specify which filtering to perform, or the user can preprocess the file by piping it through the needed filtering before passing it to `lpr` for routine print processing. There are some good magic filter packages, including APSfilter (which we have chosen to describe here) Magic-Filter, and the `gslp.ps` filter provided with complete Ghostscript packages.

Some Linux distributions, regrettably, omit Ghostscript's supplemental utilities or documents, but you can always retrieve a complete Ghostscript distribution via FTP from the GNU archive site (ftp://ftp.gnu.org/gnu/ ) or one of its mirrors. You can get the APSfilter package from the ftp://metalab.unc.edu FTP site in the /pub/Linux/system/printing directory. The primary FTP site for the Magic-Filter package is the ftp://tsx-11.mit.edu Linux archive. The Ghostscript filter, `gslp.ps`, is written in the PostScript language and can be used only with Ghostscript or another interpretor compatible with Adobe PostScript.

The APSfilter package for Linux is a port of a package developed for FreeBSD. For that reason, there are a few precautions to take in order to ensure that things configure properly when you install the APSfilter package. On a Linux host, it is probably best to install the APSfilter package in /usr/lib/apsfilter. The package comes from ftp://metalab.unc.edu as a gzipped, tarred file. To unpack the package, put it in the /usr/lib/apsfilter directory and enter:

>     gunzip apsfilter*gz

This results in a tar file. As of this writing, the tar file does not install correctly if you simply use the `tar` command on it in the apsfilter directory. Instead, from the apsfilter directory, use this command:

>     tar -vxf apsfilter*.tar -C /usr/lib

Now the APSfilter package unpacks within subdirectories of the apsfilter directory.

Change to the apsfilter directory. Before you run the `SETUP` command, you want to make sure you have all the filters you might want to use with APSfilter installed and configured. The /usr/lib/apsfilter/FAQ file tells you of some of the more important and useful packages.

Before you run the installation, read the INSTALL document to make sure there aren't any surprises. Then run ./SETUP. It tests for the presence and location of graphics utilities and other filters APSfilter uses to convert files into a form printable on your printer.

The SETUP script lets you know if the filter installed correctly. It can be run again if you wish to install more than one printer or more than one mode for a single printer. For example, if you install a Deskjet 540 printer, you probably will want to use the dj500 definition for the black cartridge and the dj550c definition for the CMYK color cartridge. APSfilter uses very long directory names for its spool directories. If you don't like that, you can rename the spool directories and change the corresponding directory fields in the corresponding `/etc/printcap` entry. Be sure not to shorten the name of the filter used; that path is critical. We don't recommend you undertake to make things pretty until you are satisfied that things are working.

Before you try your new setup, you need to restart the print daemon:

>     /usr/sbin/lpc restart all

APSfilter sets systemwide variables for printer definitions in the /etc/apsfilterrc file; reading it can be informative. Common print problems are probably the usual file ownership or permission problems, so don't forget to check that out. Then, read the FAQ and TROUBLESHOOTING files in the /usr/lib/apsfilter directory.

If your APSfilter installation didn't work, you can always return to the configuration you had before you installed it by copying the /etc/printcap.orig file that APSfilter saved for you back to /etc/printcap.

APSfilter names its printers sequentially, from `lp1` up. Don't be confused; that has nothing to do with the actual physical device assigned to the printer. Again, you can change those names.

APSfilter allows you to loosen restrictions so individual users can set up their own .apsfilterr file in their home directories. The default is to not allow it, which is a bit more secure.

The latest version of Magic-Filter (at the time of this writing, Version 1.2) is remarkably easy to install and makes a clean alternative to APSfilter. However, the installation doesn't do any hand-holding. Though there is a useful manual page, there isn't much information to walk you through setting up the alternate processing that the Magic-Filter utility should do for most printing devices. In particular, if you have a versatile printer that outputs in multiple modes (PostScript, PCL5, text, and so on), you may find it worth your while to install and use this package.

### 8.4.10. BSD Print System Elements: Files, Directories, and Utilities

The print-management system requires you to create directories that match the printcap printer names in order to spool files for printing. It also requires you to create other files for controlling the print process itself. You must set up directories and files with the correct ownership and privileges, and the printer utilities themselves also need correct permissions.

### 8.4.10.1. Setting up printer directories

Your Linux installation created a standard spool directory. Ideally, this is on a fast-access disk drive. The basic spool directory (/var/spool ) is normally used for managing mail, news, and UUCP communications as well as for holding printer files. We recommend you follow this practice, which is a Linux standard. Some utilities or filters you get may expect to find /usr/spool/lpd as the printer spool path. You will have to make corrections if you find this condition. You can, of course, create /usr/spool and link it to /var/spool, but that is a good idea only if /usr and /var are on the same disk drive.

You must create your own printer spool directories. The /var/spool/lpd directory is the standard path for each printer subdirectory. Each printer subdirectory name must be used as a printer name in the first field in a corresponding /etc/printcap entry. For example, /var/spool/lpd/moa is appropriate for a printer with `moa` in a name field of the printcap entry. In turn, the /etc/printcap entry for this printer should have an `sd` variable set to point to the spooling directory (`sd=/var/spool/lpd/moa`, for example).

You shouldn't use `lp` as the actual spool directory name unless you never expect to have more than one printer on your system or network, because `lp` is the default printer. (If your default printer is somewhere else on the network, your files will still get spooled to /var/spool/lpd/lp first, before your `lpd` forwards them to the print daemon on the remote host to print.) You may have a printer-management utility that automatically creates an `lp` spool directory, but you can always edit the printcap file to point to any directory you wish.

The spool directory name should be the first name listed in the associated /etc/printcap entry for the printer to make identification easy. The printcap entry will then be associated with the names under which `lpq` and `lpc` utilities report print queue status.

### 8.4.10.2. File, directory, and utility privileges

The most common problem in establishing print services is with file and directory permissions. Table 8-1 lists the important files, directories, and utilities that comprise BSD print management on Linux. Installed locations may vary according to your Linux distribution. The ownerships and permissions given in the following table are recommended for the files and directories of the printing system. (Additional filters and nonstandard spool paths may be specified in /etc/printcap). Different permissions may still work, but if you have permissions problems, this is where you can straighten them out. An asterisk in the first column of Table 8-1 indicates that many files can exist with the names of different printers.

#### Table 8-1. BSD's Files, Directories, and Utilities for Printing

Directory or File | Permissions | Owner/Group | Description
--- | --- | --- | ---
/dev/ttys1 | `crwsr-----` | root/lp | Typical serial port printing device
/dev/lp1 | `crws------` | root/lp | Typical parallel port device (not bidirectional)
/usr/bin/lpc | `-rwsrwsr-x` | root/lp | Controls print-spooling services
/usr/bin/lpr | `-rwsrwsr-x` | root/lp | Receives print file, assigns processing data, and spools both
/usr/bin/lpq | `-rwsrwsr-x` | root/lp | Reports on spooled files with user and print queue data
/usr/bin/lprm | `-rwsrwsr--` | root/lp | Removes print jobs from spool
/usr/bin/tunelp | `-rwsr-sr--` | root/lp | Tests print services to improve them
/usr/bin/lptest | `-rwxr-xr-x` | root/root | Outputs an ASCII file for printer and display testing
/usr/sbin/lpd | `-rwsr-s---` | root/lp | Daemon manages printing using printcap data and data passed by `lpr`
/usr/sbin/lpf | `-rwxr-xr-x` | root/lp | Primitive BSD text print filter
/usr/sbin/pac | `-rwxr--r--` | root/root | BSD utility reports on printer activity and usage by user ID
/var/spool/ | `drwxr-sr-x` | root/daemon | Basic system location for temporary files
/var/spool/lpd | `-rws--s--x` | root/lp | Standard path for the print-spooling system
/var/spool/lpd/* | `drwxr-sr-x` | root/lp | Spooling subdirectories for each defined printer
/var/spool/lpd/*/filter | `-rwxr-xr-x` | root/lp | Filters created by Red Hat printer-management utility for each print spool
/var/spool/lpd/lpd.lock | `-rw-rw----` | root/lp | `lpd` queue control lock
/var/spool/lpd/*/.seq | `-rw-rw----` | lp/lp | Sequence file `lpd` uses to order spooled files
/var/spool/lpd/*/lock | `-rw-------` | root/lp | `lpd` writes lock to prevent sending next file until printer is ready
/var/spool/lpd/*/status | `-rw-------` | lp/lp | `lpd` stores latest printer status report here
/var/log/lp-acct | `-rw-------` | root/root | Accounting record file, from which `pac` extracts and formats print data[37]
/var/log/lpd-errs | `-rw-rw-r--` | root/lp | Standard BSD log file for lpd errors

> [37]This file remains empty if system accounting is not installed, unless you configure Ghostscript to perform its limited reporting there and make the file writable by all.

The usual Linux printer-management utilities set the print files with root ownership and lp group privilege. Traditionally, BSD distributions have used root ownership and daemon group privilege. You can use either group privilege, but if you use both daemon and lp privileges with different utilities and files, you will have problems. Be particularly careful about this if you add utilities from other packages to your services.

Let's say you (as root) need to create the printer-spooling directory, /var/spool/lpd. You execute the command:

>     mkdir /var/spool/lpd

Assuming your /var/spool was created with the usual permissions, the new lpd directory has permissions of `drwxrwxr-x`, which is too permissive. If you enter the command:

>     chmod 755 /var/spool/lpd

the permissions are changed to `drwxr-xr-x`. This is close, but not what you want. You need to set the setuid bit, so lp can setuid root:

>     chmod +s /var/spool/lpd

This results in `drwsr-sr-x`, which is what you want. However, the group should be lp, not root, so you need to fix that:

>     chgrp lp /var/spool/lpd

Create the spool directories needed for each printer as subdirectories of the /var/spool/lpd directory in the same way, and then use `touch` to create a .seq file in each print directory:

>     touch .seq

### 8.4.11. Exercising the Printer Daemon

The `lpd` daemon consults /etc/printcap and then sends files to printers by directing them to a device file in the /dev directory. Most printers on Linux boxes are serial (usually addressed through devices named /dev/ttys0, /dev/ttys1, and so on, or /dev/ttyS0, /dev/ttyS1, and so on.) or parallel (/dev/lp0, /dev/lp1, or /dev/lp2, depending on the physical addresses the ports use). The port assignments are described in the section "Section 8.4.14, "Printer System Troubleshooting"." A common mistake when configuring print services is to use the wrong port.

You can link a virtual device, /dev/fax for example, to an actual device you can use by creating a symbolic link. For example:

>     ln -s /dev/ttys1 /dev/fax

This allows users to set up scripts and filters that address /dev/fax, while you move the physical device (a faxmodem, for example) around simply by removing /dev/fax and then creating it again with a link to the new device.

The BSD printer daemon is notorious for dying or just becoming inert. To be fair, this seems to be less common than it was some years ago, but it still happens. When it does, just kill the old daemon and start a new one. If `lpd` isn't fairly reliable, though, there is a cause somewhere. There could be something wrong with a user's environment or the specified command-line options used with `lpr` or a faulty filter that sends setup data to the printer in a form the printer doesn't like. However, you have every reason to expect to have a "pretty good" printing package installation. If you are having problems, check out "Section 8.4.14, "Printer System Troubleshooting"."

OK, let's see if you have a working print system. After making all these changes, you can be sure that `lpd` doesn't know what is going on. So run the `ps` command and find the ID of the `lpd` process. Then enter:

>     kill -9 processid

to kill the process you specified.[38] You should now have no print daemon running. Just enter `/usr/sbin/lpd` to start the print daemon.

> [38] You may prefer to use `lpc` to perform this task. Also, if your root desktop has a printer-manager tool, you can probably click on the lpd button to kill and restart the print daemon.

Now, while watching the activity LEDs on your printer front panel (if there are any), send a file to the printer (still acting with superuser privilege):

>     lptest | lpr

The `lptest` ASCII barber pole should begin printing to your default printer, as configured in your /etc/printcap file. If it doesn't, you have a configuration problem that has nothing to do with privileges.

Did the printer show any activity? Does your default printer have a spool directory? Does the directory have a .seq file? Check /var/log/lpd-errs and see if anything was stored in it. Use the `lpc` command and get a report on the status of the print daemon and the print spool.

If everything else looks good, make sure the printer is using the port you expected by sending a file directly to the port--for example:

>     # lptest > /dev/lp1

To test for a serial printer:

>     # lptest > /dev/ttys1

and so on. If none of these worked, reexamine your /etc/printcap file. Is your entry properly formed? Are there no blank spaces or tabs following the continuation character (\) on your entry line? Is the printer queue correctly specified? Does the name `lp` appear as one of the printer names of the name field? Is the first name in the name field the same name as the spool directory it uses?

Let's assume you got through this first little test unscathed, and you now have several pages of lovely barber-pole printout in your printer tray. Next comes the real challenge. Can you print as a regular user? Log in (or run `su`) to become a normal system user. Now, try the same experiment. If it works, congratulations, you've got a printer! If it doesn't, you have a problem, but it is probably a file or directory ownership or permissions problem. You know what you have to do about that. Become root again, look at the manual pages for `chgrp`, `chmod`, and `chown`, and go down the list of files and directories to find your problem and fix it. Repeat until Joe User can print.

### 8.4.12. Controlling Printer Services with lpc

The `lpc` utility is provided to manage printer queues and requires root privilege to perform most of its functions. `lpc` reports on all print queues and their attending `lpd` daemons. You can also specify reports on a specific printer or printing system user. To get a status report on all printers and users, type:

>     $ lpc status
>     ibis:
>     	queuing is enabled
>     	printing is enabled
>     	no entries
>     	no daemon present
>     crow:
>     	queuing is enabled
>     	printing is enabled
>     	1 entry in spool area
>     	crow is ready and printing

>     ada:
>     	queuing is disabled
>     	printing is disabled
>     	no entries
>     	no daemon present

Queuing can be enabled within `lpc` through the `enable` command and disabled using its `disable` command. The `disable` command works by setting a group execute permission on the lock file in the print spool directory.

Printing can be enabled in `lpc` using its `start` command and disabled using its `stop` command. Jobs held in a print queue when a printer is stopped will remain there until printing is restarted. The `stop` command functions by setting a lock file in the printer spool directory and killing the print daemon for that queue, but it allows the currently printing job to complete. The `abort` command works like `stop`, but halts any printing job immediately, too. (Since the job did not complete, `lpr` retains it and starts over again when the queue is restarted.)

The `down` command functions as though both a `disable` and a `stop` command were issued, and the `up` command does the reverse, issuing `enable` and `start` commands.

You could also limit the display to one printer:

>     $ lpc status crow
>     crow:
>     	queuing is enabled
>     	printing is enabled
>     	1 entry in spool area
>     	crow is ready and printing

The status-reporting feature is useful for anyone, and `lpc` allows all users to use it. The real work for `lpc` usually involves solving a printing crisis. Sometimes a print daemon dies, and printing jobs back up. Sometimes a printer runs out of ink or paper, or even fails. Jobs in the print spools have to be suspended or moved to another spool where they can be printed. Someone may simply have an urgent printing task that needs to be moved to the top of the queue.

The `lpc` command is a classic Unix command: tight-lipped and forbidding. When you simply enter the `lpc` command, all you get back is a prompt:

>     lpc>

The command is interactive and waiting for your instructions. You can get help by entering `help` or a question mark at the `lpc` prompt. `lpc` responds and gives you a new prompt. For example, entering a question mark displays:

>     #  lpc
>     lpc> ?
>     Commands may be abbreviated.  Commands are:
>     abort   enable  disable help    restart status  topq    ?
>     clean   exit    down    quit    start   stop    up
>     lpc>

You can get additional help by asking for help about a specific command. For example, to learn more about restarting a stalled print queue, type:

>     lpc> help restart
>     restart         kill (if possible) and restart a spooling daemon
>     lpc>

The `lpc` help message does not offer online help about the secondary arguments you can specify in some places. The manual page will offer you some guidance. Most of the commands accept `all` or a print spool name as a secondary argument.

The `lpc topq` command recognizes a print spool name as the first argument and printer job numbers or user IDs as following arguments. The arguments are used to reorder the print queue. For example, to move job 237 to the top of the ada print queue, followed by all jobs owned by bckeller in the queue, enter:

>     lpc> topq ada 237 bckeller

The `lpd` daemon will start job 237 as soon as the current job is finished and will put any files in the queue owned by bckeller before the rest of the print spool. If you were very impatient, you could use the `abort` and `clean` commands to kill and purge the currently printing job, then use `topq` to put the job you want at the top of the queue, before using `restart` to create a new `lpd` and restart the queue.

When you use the `stop` command to stop a print spool (or all print spools) you can broadcast a message to all system users at the same time. For example:

>     lpc> stop ada "Printer Ada taken down to replace toner cartridge."

If you do major surgery on the print spools--stopping queues and moving files around--it is wise to use `lpc`'s `clean` command. This minimizes the risk that some loose end will cause an `lpd` daemon to stall:

>     lpc> clean

Then get a new status report and restart or start all stopped print spools before exiting. There is a difference between aborting a process, stopping a process, and bringing a print queue down. If you bring a print queue down (`lpc down ada` for example) you will find you cannot get `lpd` to serve the print spool again until you restore services with an `lpc up ada` command. Similarly, if you stop a queue, you have to start or restart it.

Follow up after you clear print spool problems using `lpc`. Further status reports will let you know promptly whether the problems were actually solved.

You should not wait for disaster to become familiar with `lpc` commands, because printing jobs can pass through a Linux spool very fast, especially when a printer has lots of memory to buffer jobs sent to it. Study the manual page and work with `lpc` enough to be comfortable with the control it gives you over print spools and `lpd` daemons.

You can abbreviate subcommands unless it makes them ambiguous. For instance, in the following command, `h` stands for `help` :

>     lpc> h topq

To exit from `lpc`, enter the command:

>     lpc> quit

or:

>     lpc> exit

### 8.4.13. Printer Optimization

For performance improvement, you can first try to maximize the physical tuning of the system. You should try to determine the maximum data flow rates you can sustain to the printers you install. Don't specify a faster rate of communication than can be supported unless your printer is going to return flow control signals to the print daemon. That is, you must have bidirectional communications (and the printer must return the necessary signals) or else you must limit your transmission speeds so that data doesn't get lost en route to the printer. You may have to experiment with this to wring the best possible performance from printers limited by restricted bandwidth.

Old PC serial and parallel cards just don't have the throughput available with later cards. Newer serial cards have faster I/O processors. Newer parallel ports are typically faster and meet the EPP standard to support bidirectional communications, which may allow `lpd` to control data flow to the printer better. A significant performance improvement may be only a few dollars away.

If your printer is just plain slow and cannot buffer print jobs, there isn't much to be gained from optimizing the data-transfer rate, of course, but it may still be useful for you to use interrupt-driven flow control instead of port polling if your hardware permits.

You can try out various printer optimizations using the `tunelp` utility. Read the manual page carefully before attempting this. If a tuning procedure fails, you may need to turn the printer off and back on to reset it. Also, don't forget to use `lpc` to restart the `lpd` daemon after each change to the configuration. Back up your working setup before monkeying around with `tunelp`.

An excellent first use for `tunelp` is to cause a print job to abort on receiving a printer error and to notify you. (The default is not to abort.) Setting this up can shorten the test cycle. To cause abort on printer error, enter as root:

>     tunelp -aon

If you use a parallel port printer, and your parallel port supports interrupt-driven printing, you can use `tunelp` to accellerate printer access:

>     tunelp /dev/lp1 -i7

This example switches the port controlled by interrupt 7 to use interrupt-driven printing. If an attempt to print after this change is made fails, you should reset the port and switch back to noninterrupt driven polling:

>     tunelp /dev/lp1 -r -i0

If you don't know the interrupt this device uses, you can query with `tunelp -q on`, and the IRQ setting will be displayed.

You can probably speed up printing a bit by reducing the pause the driver takes when it cannot send a character to the printer after a certain number of tries. For example, a fast laser printer might happily accommodate very brief pauses and not require many attempts to transmit. To try putting a character 10 times before pausing (the default is 250 attempts) and set the pause to .01, type:

>     tunelp /dev/lp1 -c10 -t1

The -t takes a numeric value that represents a multiple of .01 seconds. The default pause is .1 seconds.

Note that if you find the optimal transfer rate for plain-text files, it is likely to be less efficient for graphics files, which are generally processed more slowly.

When you finish tuning your printing system, you may want to reset the printer abort flag to prevent the process from aborting on receipt of printer error:

>     tunelp -aoff

The `tunelp` utility will continue to be developed in subsequent releases of Linux. Check the manual page to see the capabilities of your release.

### 8.4.14. Printer System Troubleshooting

When you have a printer problem, first resort to `lpc` to generate a status report. The print daemons should be alive and well, and no error should be returned. You can also check the contents of the /var/spool/lpd/printername/status file and see if there is an error message from the printer stored there. Check the /var/log/lpd-errs file for any errors reported by `lpd`. If you are using Ghostscript, and its reporting features are active, use `/sbin/pac` on Ghostscript's log file to get a report that may reveal errors Ghostscript generated. (As long as Linux system accounting isn't available, you might as well use /var/log/lp-acct to store these reports. You'll have to make the file writable by all to do this.)

Look at that `lpc` status report again. Do files get to the print spool? Do they leave the spool? Are the necessary supporting files for `lpd` present (.seq, lock, and so on). If `lpc status` reported a printer named " : " there is a malformed /etc/printcap line; the last character on a continuation line must be the backslash, not a space or tab.

Sometimes the /etc/printcap file is set up wrong, and it makes `lpd` misroute a file. To test for that condition, prepare a file for print but save it to a file instead of spooling it to the printer. Examine the file. Is it in the form you expect? Try a couple of sanity checks:

- If as root you send the file directly to the device (for example, `cat filename.ps > /dev/lp1`) does it print? If so, it means the problem lies in your software configuration, not in the hardware.

- Can you view your PostScript file using Ghostview? If so, you know that the format of the file is correct but the printer or filter is not interpreting it properly.

If you are testing a text file, try preparing it and routing it to a display, passing it through a utility such as `less`, and examine the result. A custom filter can also misroute a file.

Sometimes it is difficult to figure out where a printing problem originates. Printer configuration problems can be masked (or introduced) by having defaults overridden, for example. You may have to start by looking at an individual user's printing habits and then work forward. Individual users can set environment variables in their shell startup files to specify the printer they want to use as a default, and the behavior of formatters and print filters. Default system values are often overridden by environment variables, and they in turn are overridden by option arguments passed to `lpr` on the command line or by another utility.

When a print job terminates abnormally, it may be necessary to clear the lock file for the spool before `lpd` will send another file to print from that spool (/var/spool/lpd/printername/lock). The `lpd` daemon creates the lock file and changes it on completion. You can use `lpc` to stop the print daemon and then clean up the spool before starting it again.

Some problems derive from the data-transfer process. A printer may drop characters or be unable to keep up with the data flow you are attempting to provide, especially if the printer is old and slow or if the cable is unusually long. One possible symptom of data-transfer problems is when the printer can handle plain text readily, but pauses and thrashes when trying to print graphic files. If you suspect some problem of this nature, try increasing the pause the system takes before attempting to resend data and slowing the wait loop. The `tunelp` utility lets you control this conveniently:

>     tunelp -t200 -w5

This command tells `lpd` to pause 2 seconds between attempts. The -w option sets the number of loops for the busy loop counter to read between strobe signals. Normally -w is set to 0. For more information on `tunelp`, see the section "Section 8.4.13, "Printer Optimization"."

If `lpd` never seems to run on your system, perhaps it isn't started up when the system boots. If this is the case, append a `/etc/lpd` line to the end of your /etc/rc.d/rc.local file. Most Linux distributions start `lpd` these days as part of the default installation.

Some problems may never occur unless you use another package that presents conflicts by attempting to address the same devices. For example, UUCP utilities address a serial port using a /dev/ttyS* device driver. However, UUCP is a daemon with greater privileges than lp, and (although it shouldn't) it can leave the device set with a privilege level `lpd` cannot write to.

The Linux distribution of the BSD print package is usually installed with lp group permissions. On traditional BSD print-management installations, `lpd` is owned by daemon and has daemon group privileges. (There's no special lp group to support printing.) If you think there are subtle problems relating to device access collisions by processes owned by different daemons, you can change all print utilities group privileges to daemon and, of course, change directory and file-access privileges as well. That would restore the traditional BSD configuration. A better solution would be to find the problem devices and change their ownership to lp, since UUCP will still be able to use devices lp owns. Be aware that a serial port address can be reached by a number of virtual devices linked to the actual device; you have to correctly set the ownership of the real port.

Occasionally, a user believes his print job is going to the "wrong" printer. This is usually an environment variable problem. Double-check your /etc/printcap, but also check the user's environment variables. For example, a user may have a GS_DEVICE variable set that Ghostscript uses as the default printer. If Ghostscript processing precedes `nenscript` processing, for example, the Ghostscript printer assignment could be passed to `nenscript`, overriding a NENSCRIPT or PRINTER device specification. This can also cause strange results if one parameter is overridden while others stay as before, so that, for example, a filter performs some special page layout for one printer, but the file goes to another.

Older PostScript printers may simply ignore ASCII files sent to them. If a user complains about disappearing output, maybe the file isn't getting passed through `nenscript` for PostScript encapsulation, or (very rarely) maybe `nenscript` was fooled into thinking it is already PostScript.

A multimode printer that knows when to switch modes (between PCL and plain text, for example) may still fail to eject the page and start the next file on the new page when one file of the same type is queued immediately following another of the same type. If this occurs, you can force the filter to add a formfeed at the end of each document (see the sample filter in the earlier section "Section 8.4.7, "Print Filters"") at the cost of sometimes printing unnecessary blank pages.

Parallel port printer addressing can be confusing. On an XT bus system, the first parallel port is addressed as /dev/lp0 at `0x3bc`. On the usual ISA bus system, the first parallel port device is /dev/lp1 at `0x378`, which is the second parallel port on an XT system (still the /dev/lp1 device). The usual second parallel port on an ISA bus system is /dev/lp2, as you would expect, at `0x278`. However, there are some unusual configurations out there, such as systems with three parallel ports (if installed correctly these will be addressed as /dev/lp0, /dev/lp1, and /dev/lp2). IRQ assignments may also be unusual and present a problem if you are trying to set up interrupt-driven printing.

If all else fails, review the initial installation procedure, making sure the hardware is actually connected and functional by booting another operating system if possible, testing devices as root user, and so on.

Copyright © 2001 O'Reilly & Associates. All rights reserved.